/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
(function(){
    var initializing = false, fnTest = /xyz/.test(function(){
        xyz;
    }) ? /\b_super\b/ : /.*/;
    // The base Class implementation (does nothing)
    this.Class = function(){};
  
    // Create a new Class that inherits from this class
    Class.extend = function(prop) {
        var _super = this.prototype;
    
        // Instantiate a base class (but only create the instance,
        // don't run the init constructor)
        initializing = true;
        var prototype = new this();
        initializing = false;
    
        // Copy the properties over onto the new prototype
        for (var name in prop) {
            // Check if we're overwriting an existing function
            prototype[name] = typeof prop[name] == "function" && 
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
            (function(name, fn){
                return function() {
                    var tmp = this._super;
            
                    // Add a new ._super() method that is the same method
                    // but on the super-class
                    this._super = _super[name];
            
                    // The method only need to be bound temporarily, so we
                    // remove it when we're done executing
                    var ret = fn.apply(this, arguments);        
                    this._super = tmp;
            
                    return ret;
                };
            })(name, prop[name]) :
            prop[name];
        }
    
        // The dummy class constructor
        function Class() {
            // All construction is actually done in the init method
            if ( !initializing && this.init )
                this.init.apply(this, arguments);
        }
    
        // Populate our constructed prototype object
        Class.prototype = prototype;
    
        // Enforce the constructor to be what we expect
        Class.prototype.constructor = Class;

        // And make this class extendable
        Class.extend = arguments.callee;
    
        return Class;
    };
  
    if ('undefined' === typeof Opal) {
        Opal = {};

        if ('undefined' !== typeof window) {
            window.Op = window.Opal = Op = Opal;
        }
    }
    
    Opal.assert = function(test, desc) {
      if (!test) throw new Error("assertion failed: "+desc);
    };    
    
    Opal.assert(window.jQuery,"Opal needs jQuery");
    Opal.$ = window.jQuery;
    Opal.assert(Handlebars,"Opal needs Handlebars");
    Opal.Handlebars = Handlebars;
    
    Opal.Object = Class.extend({
        
        observers: [],
        
        init: function () {
            this.$ = Opal.$;
        }
    });
    
    Opal.Application = Opal.Object.extend();
    
    Opal.Model = Opal.Object.extend();
    
    Opal.Controller = Opal.Object.extend({
        stores: {},
        views:{}
    });
    
    Opal.View = Opal.Object.extend({
       templateName: "",
       rootElement: "",
       context: {},
       template: null,
       init: function(args) {
           this.templateName = args.templateName;
           this.context = args.context;
           this.rootElement = args.rootElement;
           this.compile();
       },
       compile: function() {
           source = Opal.$(this.templateName).html();
           this.template = Opal.Handlebars.compile(source);
       },
       show: function(action) {
           html = this.template(this.context);
           if (action == "append") {
               Opal.$(this.rootElement).append(html);
           } else if (action == "clean-append") {
               Opal.$(this.rootElement).empty();
               Opal.$(this.rootElement).append(html);
           }
       },
       showLoader: function() {
         this.clean();
         Opal.$(this.rootElement).html("<div class='ajax-loader'></div>");  
       },
       hideLoader: function() {
         Opal.$(this.rootElement).find(".ajax-loader").remove();
       },
       clean: function() {
           Opal.$(this.rootElement).empty();
       }
    });
    
    Opal.Proxy = Opal.Object.extend({
       url: '',
       type: 'JSON',
       
       init: function(url) {
           this._super();
           this.url = url;
       },
       loadData: function(params,callback) {
           Opal.$.getJSON(this.url,params,function(data) {
               callback(data);
           });
       },
       sendData: function(params,callback) {
           Opal.$.getJSON(this.url,params, function(data) {
               callback(data);
           });
       }
    });
    
    Opal.Store = Opal.Object.extend({
        autoConnect: false,
        loading: false,
        paginate: false,
        currentPage: null,
        perPage: null,
        totalEntries: null,
        fields: [],
        proxy: null,        
        data: [],
        params: {},
        init: function (args) {
            this._super();
            this.fields = args.fields;
            this.params = args.params;
            this.paginate = args.paginate;
            this.url = args.url;
            this.proxy  = new Opal.Proxy(args.url+".json");
            if (this.autoConnect) {
                this.load(this.params,args.loadCallback);
            }
        },
        load: function(params,callback) {
            var me = this;
            me.loading = true;
            this.proxy.loadData(params,function(data) {
                if (me.paginate) {
                    me.data = data.entries;
                    me.currentPage = data.currentPage;
                    me.perPage = data.perPage;
                    me.totalEntries = data.totalEntries;
                }                
                me.loading = false;
                if (callback != undefined) { callback(data); }
            });
        },
        getRecordById: function(id) {
            var returnRecord = null;
            Opal.$.each(this.data,function(index,record) {
                if (record.id == id) {
                    returnRecord = record;
                    return false;
                }
                return true;
            });
            return returnRecord;
        },
        loadRecordById: function(id,callback) {            
            var onlyRecordProxy = new Opal.Proxy(this.url+"/"+id+".json");
            onlyRecordProxy.loadData(null,function(data) {
               if (callback != undefined) { callback(data); }
            });            
        }
    });
})();